/**
 * 8080a emulator by triton & ic
 *
 * Opcodes switches
 */

/* OPCODES & FLAGS macros */

#define _PARITY(b)     \
    ((!!((b)&0x80)) ^  \
    (!!((b)&0x40))  ^  \
    (!!((b)&0x20))  ^  \
    (!!((b)&0x10))  ^  \
    (!!((b)&0x08))  ^  \
    (!!((b)&0x04))  ^  \
    (!!((b)&0x02))  ^  \
    (!!((b)&0x01)))

#define PARITY(v)  \
            _PARITY(v) ? (_F|P_FLAG)  :  (_F&~P_FLAG)

#define SIGN(r)    \
            r&0x80 ? (_F|S_FLAG)  :  (_F&~S_FLAG)
// r>>7

#define ZERO(r)    \
            r==0 ? (_F|Z_FLAG)  :  (_F&~Z_FLAG)

#define AC(r)      \
            r&0xF ? (_F|AC_FLAG)  :  (_F&~AC_FLAG)

#define CARRY(r)    \
            r + r > 0xFF ? (_F|C_FLAG)  :  (_F&~C_FLAG)


#define ADDr(r)    \
            //_F |= CARRY(r) | AC(r) | ZERO(r) | SIGN(r) | PARITY(r)  \
            _F = SIGN(r); \
            _F = AC(r);   \
            break;

#define ADDp(r1, r2)     \
            _HL += _BC;  \
            break;

#define ANDc(r) _F |= (_F&(~C_FLAG)&(~AC_FLAG)) | ZERO(r) | SIGN(r) | PARITY(r)

#define ANDr(r)       \
            _A &= r;  \
            ANDc(r);  \
            break;

#define ANDm(r)                \
            _A &= MemRead(r);  \
            ANDc(r);           \
            break;



#define INCr(r)                         \
            r++;                        \
            _F |= SIGN(r) | PARITY(r) | AC(r); \
            break;
// ^ H FLAG

#define SUBr(r)    \
            break;

#define ORr(r)    \
            break;

#define CPr(r)    \
            break;

#define XORr(r)    \
            break;

#define ADCr(r)    \
            break;

#define INCp(r)   \
            r++;  \
            break;

#define DECr(r)                         \
            r--;                        \
            _F = SIGN(r) | PARITY(r) | AC(r);

#define DECp(r)                         \
            r--;                        \
            break;

#define  _A   R->AF.reg.A
#define  _B   R->BC.reg.B
#define  _C   R->BC.reg.C
#define  _D   R->DE.reg.D
#define  _E   R->DE.reg.E
#define  _H   R->HL.reg.H
#define  _L   R->HL.reg.L
#define  _BC  R->BC.pair
#define  _DE  R->DE.pair
#define  _HL  R->HL.pair
#define  _F   R->AF.reg.F
#define  _PC  R->PC
#define  _SP  R->SP

///////////////////////////////////
//       LOAD AND EXCHANGE       //
///////////////////////////////////

#define LDrr(r1,r2)  \
            r1=r2;   \
            break;

#define LDri(r)                  \
            r = MemRead(_PC++);  \
            break;

#define LDpi(r)                                        \
            r = (MemRead(_PC+1) << 8) | MemRead(_PC);  \
            _PC += 2;                                  \
            break;

#define LDmr(off, r)       \
        MemWrite(off, r);  \
        break;

#define LDmi(off, n)       \
		LDmr(off, n)

#define PUSH(r)            \
            // todo
            break;

#define POP(r)            \
            // todo
            break;

// --------- 81 LD r, r'
case LD_A_A:  LDrr(_A,_A)
case LD_A_B:  LDrr(_A,_B)
case LD_A_C:  LDrr(_A,_C)
case LD_A_D:  LDrr(_A,_D)
case LD_A_E:  LDrr(_A,_E)
case LD_A_H:  LDrr(_A,_H)
case LD_A_L:  LDrr(_A,_L)
// ---------
case LD_B_A:  LDrr(_B,_A)
case LD_B_B:  LDrr(_B,_B)
case LD_B_C:  LDrr(_B,_C)
case LD_B_D:  LDrr(_B,_D)
case LD_B_E:  LDrr(_B,_E)
case LD_B_H:  LDrr(_B,_H)
case LD_B_L:  LDrr(_B,_L)
// ---------
case LD_C_A:  LDrr(_C,_A)
case LD_C_B:  LDrr(_C,_B)
case LD_C_C:  LDrr(_C,_C)
case LD_C_D:  LDrr(_C,_D)
case LD_C_E:  LDrr(_C,_E)
case LD_C_H:  LDrr(_C,_H)
case LD_C_L:  LDrr(_C,_L)
// ---------
case LD_D_A:  LDrr(_D,_A)
case LD_D_B:  LDrr(_D,_B)
case LD_D_C:  LDrr(_D,_C)
case LD_D_D:  LDrr(_D,_D)
case LD_D_E:  LDrr(_D,_E)
case LD_D_H:  LDrr(_D,_H)
case LD_D_L:  LDrr(_D,_L)
// ---------
case LD_E_A:  LDrr(_E,_A)
case LD_E_B:  LDrr(_E,_B)
case LD_E_C:  LDrr(_E,_C)
case LD_E_D:  LDrr(_E,_D)
case LD_E_E:  LDrr(_E,_E)
case LD_E_H:  LDrr(_E,_H)
case LD_E_L:  LDrr(_E,_L)

// --------- 82 LD r, n
case LD_A_i:  LDri(_A)
case LD_B_i:  LDri(_B)
case LD_C_i:  LDri(_C)
case LD_D_i:  LDri(_D)
case LD_E_i:  LDri(_E)
case LD_H_i:  LDri(_H)
case LD_L_i:  LDri(_L)

// --------- 83 LD r, (HL)
case LD_A_mHL:    LD_r_m(AF.reg.A, HL.pair);
case LD_B_mHL:    LD_r_m(BC.reg.B, HL.pair);
case LD_C_mHL:    LD_r_m(BC.reg.C, HL.pair);
case LD_D_mHL:    LD_r_m(DE.reg.D, HL.pair);
case LD_E_mHL:    LD_r_m(DE.reg.E, HL.pair);
case LD_H_mHL:    LD_r_m(HL.reg.H, HL.pair);
case LD_L_mHL:    LD_r_m(HL.reg.L, HL.pair);

// --------- 84 LD r, (IX+d)

// --------- 85 LD r, (IY+d)

// --------- 86 LD (HL), r
case LD_mHL_A:    MemWrite(HL.pair, AF.reg.A);
case LD_mHL_B:    MemWrite(HL.pair, BC.reg.B);
case LD_mHL_C:    MemWrite(HL.pair, BC.reg.C);
case LD_mHL_D:    MemWrite(HL.pair, DE.reg.D);
case LD_mHL_E:    MemWrite(HL.pair, DE.reg.E);
case LD_mHL_H:    MemWrite(HL.pair, HL.reg.H);
case LD_mHL_L:    MemWrite(HL.pair, HL.reg.L);

// --------- 87 LD (IX+d), r

// --------- 88 LD (IY+d), r

// --------- 89 LD (HL), n
case LD_mHL_i:    MemWrite(HL.pair,MemRead(PC.pair++));

// --------- 90 LD (IX+d), n

// --------- 91 LD (IY+d), n

// --------- 92 LD A, (BC)
case LD_A_mBC:    LD_r_m(AF.reg.A, BC.pair);

// --------- 93 LD A, (DE)
case LD_A_mDE:    LD_r_m(AF.reg.A, DE.pair);

// --------- 94 LD A, (nn)
case LD_A_mii:     break;

// --------- 95 LD (BC), A
case LD_mBC_A:    MemWrite(BC.pair, AF.reg.A);

// --------- 96 LD (DE), A
case LD_mDE_A:    MemWrite(DE.pair, AF.reg.A);

// --------- 97 LD (nn), A
case LD_mii_A:     break;

// --------- 98 LD A, I [F]
//case LD_A_I:	break;

// --------- 99 LD A, R [F]
//case LD_A_R:	break;

// --------- 100 LD I, A
//case LD_I_A:	break;

// --------- 101 LD R, A
//case LD_R_A:	break;

// --------- 102 LD dd, nn
case LD_BC_ii:  LDpi(_BC)
case LD_DE_ii:  LDpi(_DE)
case LD_HL_ii:  LDpi(_HL)
case LD_SP_ii:  LDpi(_SP)

// --------- 103 LD IX, nn

// --------- 104 LD IY, nn

// --------- 105 LD HL, (nn)
case LD_HL_mii:    break;

// --------- 106 LD dd, (nn)
case LD_DE_ii:     LD_pp_i(DE.reg.D,DE.reg.E);
case LD_BC_ii:     LD_pp_i(BC.reg.B,BC.reg.C);
case LD_HL_ii:     LD_pp_i(HL.reg.H,HL.reg.L);
case LD_SP_ii:     LD_pp_i(SP.reg.S,SP.reg.P);

// --------- 107 LD IX, (nn)

// --------- 108 LD IY, (nn)

// --------- 109 LD (nn), HL
case LD_mii_HL:    break;

// --------- 110 LD (nn), dd
case LD_mBC_A:  LDmr(_BC,_A)
case LD_mDE_A:  LDmr(_DE,_A)
case LD_mHL_A:  LDmr(_HL,_A)
case LD_mHL_B:  LDmr(_HL,_B)

// --------- 111 LD (nn), IX

// --------- 112 LD (nn), IY

// --------- 113 LD SP, HL
case LD_SP_HL:    _SP = _HL; break;

// --------- 114 LD SP, IX

// --------- 115 LD SP, IY

// --------- 116 PUSH qq
case PUSH_BC:	PUSH(_BC)
case PUSH_DE:	PUSH(_DE)
case PUSH_HL:	PUSH(_HL)
case PUSH_AF:	PUSH(_AF)

// --------- 117 PUSH IX

// --------- 117 PUSH IY

// --------- 119 PUSH qq
case POP_BC:	POP(_BC)
case POP_DE:	POP(_DE)
case POP_HL:	POP(_HL)
case POP_AF:	POP(_AF)

// --------- 120 POP IX

// --------- 121 POP IY


////////////////////////////////////////////////
// EXCHANGE, BLOCK TRANSFER, AND SEARCH GROUP //
////////////////////////////////////////////////

// --------- 122 EX DE, HL
case EX_DE_HL:

// --------- 123 EX AF, AF'
case EX_AF_AFx:

// --------- 124 EXX
case EXX:

// --------- 125 EX (SP), HL
case EX_mSP_HL:

// --------- 126 EX (SP), IX

// --------- 127 EX (SP), IY

// --------- 128 LDI [F]

// --------- 129 LDIR [F]

// --------- 131 LDD [F]

// --------- 132 LDDR [F]

// --------- 134 CPI [F]

// --------- 135 CPIR [F]

// --------- 137 CPD [F]

// --------- 137 CPDR [F]

//////////////////////////////////////
//  ARITHMETIC AND LOGICAL (8-BIT)  //
//////////////////////////////////////

// --------- 140,141 ADD A, r [F]
case ADD_A_A: ADDr(_A)
case ADD_A_B: ADDr(_B)
case ADD_A_C: ADDr(_C)
case ADD_A_D: ADDr(_D)
case ADD_A_E: ADDr(_E)
case ADD_A_H: ADDr(_H)
case ADD_A_L: ADDr(_L)

// --------- 142 ADD A, n [F]
case ADD_i:

// --------- 143 ADD A, (HL) [F]
case ADD_A_mHL:

// --------- 144 ADD A, (IX + d) [F]

// --------- 145 ADD A, (IY + d) [F]

// --------- 146,147 ADC A, r [F]
case ADC_A_A: ADCr(_A)
case ADC_A_B: ADCr(_B)
case ADC_A_C: ADCr(_C)
case ADC_A_D: ADCr(_D)
case ADC_A_E: ADCr(_E)
case ADC_A_H: ADCr(_H)
case ADC_A_L: ADCr(_L)

// --------- 146,147 ADC A, n [F]
case ADC_A_i:

// --------- 146,147 ADC A, (HL) [F]
case ADC_mHL:

// --------- 146,147 ADC A, (IX + d) [F]

// --------- 146,147 ADC A, (IY + d) [F]

// --------- 148,149 SUB A, r [F]
case SUB_A_A: _A=0;_F=N_FLAG|Z_FLAG;break;
case SUB_A_B: SUBr(_B)
case SUB_A_C: SUBr(_C)
case SUB_A_D: SUBr(_D)
case SUB_A_E: SUBr(_E)
case SUB_A_H: SUBr(_H)
case SUB_A_L: SUBr(_L)

// --------- 148,149 SUB A, n [F]
case SUB_A_i:

// --------- 148,149 SUB A, (HL) [F]
case SUB_A_mHL:

// --------- 148,149 SUB A, (IX + d) [F]

// --------- 148,149 SUB A, (IY + d) [F]

// --------- 150,151 SBC A, r [F]
case SBC_A_A: 
case SBC_A_B: 
case SBC_A_C: 
case SBC_A_D: 
case SBC_A_E: 
case SBC_A_H: 
case SBC_A_L:

// --------- 150,151 SBC A, n [F]
case SBC_A_i:

// --------- 150,151 SBC A, (HL) [F]
case SBC_A_mHL:

// --------- 150,151 SBC A, (IX + d) [F]

// --------- 150,151 SBC A, (IY + d) [F]

// --------- 152,153 AND A, r [F]
case AND_A_A: ANDr(_A)
case AND_A_B: ANDr(_B)
case AND_A_C: ANDr(_C)
case AND_A_D: ANDr(_D)
case AND_A_E: ANDr(_E)
case AND_A_H: ANDr(_H)
case AND_A_L: ANDr(_L)

// --------- 152,153 AND A, n [F]
case AND_A_i:

// --------- 152,153 AND A, (HL) [F]
case AND_A_mHL: ANDm(_HL)

// --------- 152,153 AND A, (IX + d) [F]

// --------- 152,153 AND A, (IY + d) [F]

// --------- 154,155 OR A, r [F]
case OR_A_A: ORr(_A)
case OR_A_B: ORr(_B)
case OR_A_C: ORr(_C)
case OR_A_D: ORr(_D)
case OR_A_E: ORr(_E)
case OR_A_H: ORr(_H)
case OR_A_L: ORr(_L)

// --------- 154,155 OR A, n [F]
case OR_A_i:

// --------- 154,155 OR A, (HL) [F]
case OR_A_mHL: ORm(_HL)

// --------- 154,155 OR A, (IX + d) [F]

// --------- 154,155 OR A, (IY + d) [F]

// --------- 156,157 XOR A, r [F]
case XOR_A_A: XORr(_A)
case XOR_A_B: XORr(_B)
case XOR_A_C: XORr(_C)
case XOR_A_D: XORr(_D)
case XOR_A_E: XORr(_E)
case XOR_A_H: XORr(_H)
case XOR_A_L: XORr(_L)

// --------- 156,157 XOR A, n [F]
case XOR_A_i:

// --------- 156,157 XOR A, (HL) [F]
case XOR_A_mHL: XORm(_HL)

// --------- 156,157 XOR A, (IX + d) [F]

// --------- 156,157 XOR A, (IY + d) [F]

// --------- 158,159 CP A, r [F]
case CP_A_A: CPr(_A)
case CP_A_B: CPr(_B)
case CP_A_C: CPr(_C)
case CP_A_D: CPr(_D)
case CP_A_E: CPr(_E)
case CP_A_H: CPr(_H)
case CP_A_L: CPr(_L)

// --------- 158,159 CP A, n [F]
case CP_A_i:

// --------- 158,159 CP A, (HL) [F]
case CP_A_mHL: CPm(_HL)

// --------- 158,159 CP A, (IX + d) [F]

// --------- 158,159 CP A, (IY + d) [F]

// --------- 160 INC r
case INC_A:  INCr(_A)
case INC_B:  INCr(_B)
case INC_C:  INCr(_C)
case INC_D:  INCr(_D)
case INC_E:  INCr(_E)
case INC_H:  INCr(_H)
case INC_L:  INCr(_L)

// --------- 161 INC (HL)
case INC_mHL:

// --------- 162 INC (IX+d)

// --------- 163 INC (IY+d)

// --------- 164,165 DEC r
case DEC_A:  DECr(_A)
case DEC_B:  DECr(_B)
case DEC_C:  DECr(_C)
case DEC_D:  DECr(_D)
case DEC_E:  DECr(_E)
case DEC_H:  DECr(_H)
case DEC_L:  DECr(_L)

// --------- 164,165 DEC (HL)
case DEC_mHL:

// --------- 164,165 DEC (IX+d)

// --------- 164,165 DEC (IY+d)

//////////////////////////////////////////////////
//  GENERAL PURPOSE ARITHMETIC AND CPU CONTROL  //
//////////////////////////////////////////////////

// General-Purpose AF operations

// --------- 166,167 DAA (Decimal Adjust Ace) [F]
case DAA:

// --------- 168 CPL (Complement Ace) [F]
case CPL:

// --------- 169 NEG (Negate Ace - 2's complement) [F]
//case NEG:

// --------- 170 CCF (Complement Carry Flag) [F]
case CCF:

// --------- 171 SCF (Set Carry Flag) [F]
case SCF:

// --------- 172 NOP (No Operation) 
case NOP:

// --------- 173 HALT (Suspends CPU)
case HALT:

// --------- 174 DI (Disable Interrupts)
case DI:

// --------- 175 EI (Enable Interrupts)
case EI:

// --------- 176,177,178 IM (Interrupt Mode)
//case IM:

//////////////////////////////////////
// ARITHMETIC AND LOGICAL (16-BIT)  //
//////////////////////////////////////

// --------- 179 ADD HL, ss [F]
case ADD_HL_BC: ADDp(_HL, _BC)
case ADD_HL_DE: ADDp(_HL, _DE)
case ADD_HL_HL: ADDp(_HL, _HL)
case ADD_HL_SP: ADDp(_HL, _SP)

// --------- 180 ADC HL, ss [F]

// --------- 181 SBC HL, ss [F]

// --------- 182 ADD IX, pp [F]

// --------- 183 ADD IY, pp [F]

// --------- 184 INC ss
case INC_BC:  INCp(_BC)
case INC_DE:  INCp(_DE)
case INC_HL:  INCp(_HL)
case INC_SP:  INCp(_SP)

// --------- 185 INC IX

// --------- 186 INC IY

// --------- 187 DEC ss
case DEC_BC:  DECp(_BC)
case DEC_DE:  DECp(_DE)
case DEC_HL:  DECp(_HL)
case DEC_SP:  DECp(_SP)

// --------- 188 DEC IX

// --------- 189 DEC IY

///////////////////////////////////
//       ROTATE AND SHIFT        //
///////////////////////////////////




///////////////////////////////////
//       BIT MANIPULATION        //
///////////////////////////////////



///////////////////////////////////
// JUMP, CALL, AND RETURN GROUP  //
///////////////////////////////////

// Jump
case JR_NZ:
case JR_NC:
case JP_NZ:
case JP_NC: break;

// Call
case CALL:
case CALL_Z:
case CALL_NZ:
case CALL_C:
case CALL_NC:
case CALL_M:
case CALL_P:
case CALL_PE:
case CALL_PO: break;

// Return
case RET:
case RET_Z:
case RET_NZ:
case RET_C:
case RET_NC:
case RET_P:
case RET_M:
case RET_PE:
case RET_PO: break;


///////////////////////////////////
//      Misc. CPU Control        //
///////////////////////////////////





#undef  _A
#undef  _B
#undef  _C
#undef  _D
#undef  _E
#undef  _H
#undef  _L
#undef  _BC
#undef  _DE
#undef  _HL
#undef  _F
#undef  _PC
#undef  _SP
